package edu.up.firesawakening;

import java.util.Vector;

import edu.up.firesawakening.TacticsGame.Move;
import edu.up.firesawakening.TacticsGame.MoveType;

/**
 * A player that is controlled by the AI. Responds to the game state accordingly
 * each turn.
 */
public class TacticsModerateComputerPlayer extends TacticsComputerPlayer {
	/**
	 * Determines the value of a state from this player's perspective.
	 * 
	 * Currently, rushes the enemy castle
	 * 
	 * @param state
	 *            the state to evaluate
	 * @return a number representing the state's value
	 */
	@Override
	protected double evaluateState(TacticsGame state) {

		// First check if game is over
		int winner = state.getWinnerId();

		if (winner == m_id) {
			return 1;
		} else if (winner != TacticsGame.NO_WINNER) {
			return -1;
		}

		// Now, eval the state
		double util = 0;

		Tile[][] map = state.getMap();

		// Unit healths (better than count probably, since this way they'll
		// always attack)
		double friendHealth = 0;
		double enemyHealth = 0;

		// Castle healths. This makes the AI try to kill the enemy castle
		// whenever possible
		double myCastleHealthPercent = 0;
		double theirCastleHealthPercent = 0;

		// Distance from enemy castle. This is so the AI will move its units
		// towards the enemy castle when no better moves are available
		double distanceFromCastle = 0;

		int attackAvailable = 0;

		Tile enemyCastle = null;

		Vector<Tile> myUnitTiles = getUnitsFromState(state, true);
		Vector<Tile> theirUnitTiles = getUnitsFromState(state, false);

		// First find their castle
		for (Tile t : theirUnitTiles) {
			Unit u = t.getUnit();

			if (u instanceof Castle) {
				enemyCastle = t;
				theirCastleHealthPercent = (double) u.getHealth()
						/ u.getMaxHealth();
			} else {
				enemyHealth += u.getHealth();
			}
		}

		// This should never happen
		if (enemyCastle == null)
			return 1;

		// Get friendly info
		for (Tile t : myUnitTiles) {
			Unit u = t.getUnit();

			// Get healths
			if (u instanceof Castle) {
				myCastleHealthPercent = (double) u.getHealth()
						/ u.getMaxHealth();
			} else {
				friendHealth += u.getHealth();

				// Get distance from enemy castle (in form of percent of
				// possible distance)
				distanceFromCastle += TacticsGame.distanceBetween(t,
						enemyCastle) / (map.length + map[0].length);

				// See if we have an attack
				Move[][] unitMoves = state.availableActions(t);
				for (int x = 0; x < unitMoves.length && attackAvailable != 1; x++) {
					for (int y = 0; y < unitMoves[0].length
							&& attackAvailable != 1; y++) {
						if (unitMoves[x][y].move == MoveType.ATTACK) {
							attackAvailable = 1;
							break;
						}
					}
				}
			}
		}

		// Get the percent of total health that is ours (this could be
		// separated?)
		double healthPercent = friendHealth / (friendHealth + enemyHealth);

		// Set distance to average percent, so it will be from 0 to 1
		distanceFromCastle /= myUnitTiles.size() - 1;

		// Weights (these should add up to 1!)

		// This is high so that the AI will usually attack enemy units when
		// possible
		util += healthPercent * 0.40;

		// This is actually irrelevant unless we start looking forward states
		util += myCastleHealthPercent * 0.00;

		// This is high so that attacking their castle is a top priority
		util += (1 - theirCastleHealthPercent) * 0.50;

		// This is very small, only used as a tie-breaker when nothing better is
		// around
		util += (1 - distanceFromCastle) * 0.01;

		// This is large enough to overcome castle distance, so that the AI
		// won't ignore possible attacks to move to the castle
		util += attackAvailable * 0.04;

		return util;
	}

}
